package com.alibaba.cloud.encry;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Hex;


/**
 * The Class RSAUtil.
 *
 * @ClassName: RSA
 * @Description:rsa 非对称 加密方式 客户端
 * @author: zhb zhb1316783262@163.com
 * @date: 2018年3月14日 下午7:04:02
 */
public class RSAUtil {
    
    /** 签名对象. */
    private static Signature signature = null;
    
    /** key生成工厂. */
    private static KeyFactory keyFactory = null;

    /**
     * @Description: 初始化生成公钥和私钥对
     * @author: zhb zhb1316783262@163.com
     * @date: 2018年3月13日 下午3:13:22
     */
    static {
        try {
            // 签名
            signature = Signature.getInstance("MD5withRSA");
            keyFactory = KeyFactory.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

    }

    /**
     * Generate public key.
     *
     * @param pubKey the pub key
     * @return the public key
     * @throws Exception the exception
     * @Description:生成公钥 
     * @author: zhb zhb1316783262@163.com
     * @date: 2018年3月14日 下午6:39:00
     */
    public static PublicKey generatePublicKey(String pubKey) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(pubKey));
        // 取公钥匙对象
        return keyFactory.generatePublic(x509EncodedKeySpec);
    }

    /**
     * Encode pub key.
     *
     * @param pubKey the pub key
     * @param src the src
     * @return the string
     * @Description:公钥加密 
     * @author: zhb zhb1316783262@163.com
     * @date: 2018年3月13日 下午3:08:58
     */
    public static String encodePubKey(String pubKey, String src) {
        try {
            PublicKey publicKey = generatePublicKey(pubKey);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] resultBytes = cipher.doFinal(src.getBytes());
            return Hex.encodeHexString(resultBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Encrypt BASE 64.
     *
     * @param key the key
     * @return the string
     * @throws Exception the exception
     * @Description: 编码返回字符串
     * @author: zhb zhb1316783262@163.com
     * @date: 2018年3月14日 下午7:06:13
     */
    public static String encryptBASE64(String key) throws Exception {
        return Base64Util.encode(key);
    }

    /**
     * Decrypt BASE 64.
     *
     * @param key the key
     * @return the string
     * @throws Exception the exception
     * @Description: 解码返回byte
     * @author: zhb zhb1316783262@163.com
     * @date: 2018年3月14日 下午7:06:22
     */
    public static String decryptBASE64(String key) throws Exception {
        return Base64Util.decode(key);
    }

    /**
     * Decode pub key.
     *
     * @param pubKey the pub key
     * @param src the src
     * @return the string
     * @Description: 公钥解密
     * @author: zhb zhb1316783262@163.com
     * @date: 2018年3月13日 下午3:11:38
     */
    public static String decodePubKey(String pubKey, String src) {
        try {
            PublicKey publicKey = generatePublicKey(pubKey);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] resultBytes = cipher.doFinal(Hex.decodeHex(src.toCharArray()));
            return new String(resultBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Verify sign.
     *
     * @param pubKey the pub key
     * @param content the content
     * @param sign the sign
     * @return true, if successful
     * @Description: 数字签名校验
     * @author: zhb zhb1316783262@163.com
     * @date: 2018年3月13日 下午3:28:36
     */
    public static boolean verifySign(String pubKey, String content, byte[] sign) {
        try {
            PublicKey publicKey = generatePublicKey(pubKey);
            signature.initVerify(publicKey);
            signature.update(content.getBytes());
            return signature.verify(sign);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}